<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="Joshua Neal">
   <META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
   <META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
   <TITLE>VGA/SVGA Video Programming--Accessing the VGA Display Memory</TITLE>
</HEAD>
<BODY>

<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#detect">Detecting</A>
<A HREF="#mapping">Mapping</A> <A HREF="#address">Addressing</A> <A HREF="#manip">Manipulating</A>
<A HREF="#read">Reading</A> <A HREF="#write">Writing</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>

<CENTER>Accessing the VGA Display Memory&nbsp;
<HR WIDTH="100%"></CENTER>

<UL>
<LI>
<A HREF="#intro">Introduction</A> -- gives an overview of the VGA display
memory.</LI>

<LI>
<A HREF="#detect">Detecting the Amount of Display Memory on the Adapter</A>
-- details how to determine the amount of memory present on the VGA.</LI>

<LI>
<A HREF="#mapping">Mapping of Display Memory into CPU Address Space</A>
-- details how to control the location and size of the memory aperture.</LI>

<LI>
<A HREF="#address">Host Address to Display Address Translation</A> -- detail
how the VGA hardware maps a host access to a display memory access</LI>

<LI>
<A HREF="#manip">Manipulating Display Memory</A> -- Details on reading
and writing to VGA memory</LI>

<UL>
<LI>
<A HREF="#read">Reading from Display Memory</A> -- Details the hardware
mechanisms used when reading display memory.</LI>

<LI>
<A HREF="#write">Writing to Display Memory</A> -- Details the hardware
mechanisms used when writing display memory.</LI>
</UL>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The standard VGA hardware
contains up to 256K of onboard display memory. While it would seem logical
that this memory would be directly available to the processor, this is
not the case. The host CPU accesses the display memory through a window
of up to 128K located in the high memory area. (Note that many SVGA chipsets
provide an alternate method of accessing video memory directly, called
a Linear Frame Buffer.) Thus in order to be able to access display memory
you must deal with registers that control the mapping into host address
space. To further complicate things, the VGA hardware provides support
for memory models similar to that used by the monochrome, CGA, EGA, and
MCGA adapters. In addition, due to the way the VGA handles 16 color modes,
additional hardware is included that can speed access immensely. Also,
hardware is present that allows the programer to rapidly copy data from
one area of display memory to another. While it is quite complicated to
understand, learning to utilize the VGA's hardware at a low level can vastly
improve performance. Many game programmers utilize the BIOS mode 13h, simply
because it offers the simplest memory model and doesn't require having
to deal with the VGA's registers to draw pixels. However, this same decision
limits them from being able to use the infamous X modes, or higher resolution
modes.

<P><A NAME="detect"></A><B>Detecting the Amount of Display Memory on the
Adapter</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Most VGA cards in
existence have 256K on board; however there is the possibility that some
VGA boards have less. To actually determine further if the card has 256K
one must actually write to display memory and read back values. If RAM
is not present in a location, then the value read back will not equal the
value written. It is wise to utilize multiple values when doing this, as
the undefined result may equal the value written. Also, the card may alias
addresses, causing say the same 64K of RAM to appear 4 times in the 256K
address space, thus it is wise to change an address and see if the change
is reflected anywhere else in display memory. In addition, the card may
buffer one location of video memory in the chipset, making it appear that
there is RAM at an address where there is none present, so you may have
to read or write to a second location to clear the buffer. Not that if
the <A HREF="seqreg.htm#04">Extended Memory</A> field is not set to 1,
the adapter appears to only have 64K onboard, thus this bit should be set
to 1 before attempting to determine the memory size.

<P><A NAME="mapping"></A><B>Mapping of Display Memory into CPU Address
Space</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The first element that defines
this mapping is whether or not the VGA decodes accesses from the CPU. This
is controlled by the <A HREF="extreg.htm#3CCR3C2W">RAM Enable</A> field.
If display memory decoding is disabled, then the VGA hardware ignores writes
to its address space. The address range that the VGA hardware decodes is
based upon the <A HREF="graphreg.htm#06">Memory Map Select</A> field. The
following table shows the address ranges in absolute 32-bit form decoded
for each value of this field:
<UL>
<LI>
00 -- A0000h-BFFFFh -- 128K</LI>

<LI>
01 -- A0000h-AFFFFh -- 64K</LI>

<LI>
10 -- B0000h-B7FFFh -- 32K</LI>

<LI>
11 -- B8000h-BFFFFh -- 32K</LI>
</UL>
Note -- It would seem that by setting the <A HREF="graphreg.htm#06">Memory
Map Select</A> field to 00 and then using planar memory access that you
could gain access to more than 256K of memory on an SVGA card. However,
I have found that some cards simply mirror the first 64K twice within the
128K address space. This memory map is intended for use in the Chain Odd/Even
modes, eliminating the need to use the Odd/Even Page Select field. Also
I have found that MS-DOS memory managers don't like this very much and
are likely to lock up the system if configured to use the area from B0000h-B7FFFh
for loading device drivers high.

<P><A NAME="address"></A><B>Host Address to Display Address Translation</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The most complicated part
of accessing display memory involves the translation between a host address
and a display memory address. Internally, the VGA has a 64K 32-bit memory
locations. These are divided into four 64K bit planes. Because the VGA
was designed for 8 and 16 bit bus systems, and due to the way the Intel
chips handle memory accesses, it is impossible for the host CPU to access
the bit planes directly, instead relying on I/O registers to make part
of the memory accessible. The most straightforward display translation
is where a host access translates directly to a display memory address.
What part of the particular 32-bit memory location is dependent on certain
registers and is discussed in more detail in Manipulating Display Memory
below. The VGA has three modes for addressing, Chain 4, Odd/Even mode,
and normal mode:
<UL>
<LI>
Chain 4: This mode is used for MCGA emulation in the 320x200 256-color
mode. The address is mapped to memory MOD 4 (shifted right 2 places.)</LI>
</UL>
<B>&lt;More to be added here.></B>

<P><A NAME="manip"></A><B>Manipulating Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware contains
hardware that can perform bit manipulation on data and allow the host to
operate on all four display planes in a single operation. These features
are fairly straightforward, yet complicated enough that most VGA programmers
choose to ignore them. This is unfortunate, as properly utilization of
these registers is crucial to programming the VGA's 16 color modes. Also,
knowledge of this functionality can in many cases enhance performance in
other modes including text and 256 color modes. In addition to normal read
and write operations the VGA hardware provides enhanced operations such
as the ability to perform rapid comparisons, to write to multiple planes
simultaneously, and to rapidly move data from one area of display memory
to another, faster logical operations (AND/OR/XOR) as well as bit rotation
and masking.

<P><A NAME="read"></A><B>Reading from Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware has two
read modes, selected by the <A HREF="graphreg.htm#05">Read Mode</A> field.
The first is a straightforward read of one or more consecutive bytes (depending
on whether a byte, word or dword operation is used) from one bit plane.
The value of the <A HREF="graphreg.htm#04">Read Map Select</A> field is
the page that will be read from. The second read mode returns the result
of a comparison of the display memory and the <A HREF="graphreg.htm#02">Color
Compare</A> field and masked by the <A HREF="graphreg.htm#07">Color Don't
Care</A> field. This mode which can be used to rapidly perform up to 32
pixel comparisons in one operation in the planar video modes, helpful for
the implementation of fast flood-fill routines. A read from display memory
also loads a 32 bit latch register, one byte from each plane. This latch
register, is not directly accessible from the host CPU; rather it can be
used as data for the various write operations. The latch register retains
its value until the next read and thus may be used with more than one write
operation.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The two read modes, simply called
Read Mode 0-1 based on the value of the <A HREF="graphreg.htm#05">Read
Mode</A> field are:
<UL>
<LI>
<B>Read Mode 0:</B></LI>

<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Read Mode 0 is used to read one
byte from a single plane of display memory. The plane read is the value
of the <A HREF="graphreg.htm#04">Read Map Select</A> field. In order to
read a single pixel's value in planar modes, four read operations must
be performed, one for each plane. If more than one bytes worth of data
is being read from the screen it is recommended that you read it a plane
at a time instead of having to perform four I/O operations to the <A HREF="graphreg.htm#04">Read
Map Select</A> field for each byte, as this will allow the use of faster
string copy instructions and reduce the number I/O operations performed.
<LI>
<B>Read Mode 1:</B></LI>

<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Read Mode 1 is used to perform
comparisons against a reference color, specified by the <A HREF="graphreg.htm#02">Color
Compare</A> field. If a bit is set in the <A HREF="graphreg.htm#07">Color
Don't Care</A> field then the corresponding color plane is considered for
by the comparison, otherwise it is ignored. Each bit in the returned result
represents one comparison between the reference color from the <A HREF="graphreg.htm#02">Color
Compare</A> field, with the bit being set if the comparison is true. This
mode is mainly used by flood fill algorithms that fill an area of a specific
color, as it requires 1/4 the number of reads to determine the area that
needs to be filled in addition to the additional work done by the comparison.
Also an efficient "search and replace" operation that replaces one color
with another can be performed when this mode is combined with Write Mode
3.</UL>
<A NAME="write"></A><B>Writing to Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA has four write modes,
selected by the <A HREF="graphreg.htm#05">Write Mode</A> field. This controls
how the write operation and host data affect the display memory. The VGA,
depending on the <A HREF="graphreg.htm#05">Write Mode</A> field performs
up to five distinct operations before the write affects display memory.
Note that not all write modes use all of pipelined stages in the write
hardware, and others use some of the pipelined stages in different ways.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The first of these allows
the VGA hardware to perform a bitwise rotation on the data written from
the host. This is accomplished via a barrel rotator that rotates the bits
to the right by the number of positions specified by the <A HREF="graphreg.htm#03">Rotate
Count</A> field. This performs the same operation as the 8086 ROR instruction,
shifting bits to the right (from bit 7 towards bit 0.) with the bit shifted
out of position 0 being "rolled" into position 7. Note that if the rotate
count field is zero then no rotation is performed.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The second uses the <A HREF="graphreg.htm#01">Enable
Set/Reset</A> and <A HREF="graphreg.htm#00">Set/Reset</A> fields. These
fields can provide an additional data source in addition to the data written
and the latched value from the last read operation performed. Normally,
data from the host is replicated four times, one for each plane. In this
stage, a 1 bit in the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
will cause the corresponding bit plane to be replaced by the bit value
in the corresponding <A HREF="graphreg.htm#00">Set/Reset</A> field location,
replicated 8 times to fill the byte, giving it either the value 00000000b
or 11111111b. If the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
for a given plane is 0 then the host data byte is used instead. Note that
in some write modes, the host data byte is used for other purposes, and
the set/reset register is always used as data, and in other modes the set/reset
mechanism is not used at all.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The third stage performs logical operations
between the host data, which has been split into four planes and is now
32-bits wide, and the latch register, which provides a second 32-bit operand.
The <A HREF="graphreg.htm#03">Logical Operation</A> field selects the operation
that this stage performs. The four possibilities are: NOP (the host data
is passed directly through, performing no operation), AND (the data is
logically ANDed with the latched data.), OR (the data is logically ORed
with the latched data), and XOR (the data is logically XORed with the latched
data.) The result of this operation is then passed on. whilst the latched
data remains unchanged, available for use in successive operations.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In the fourth stage, individual
bits may be selected from the result or copied from the latch register.
Each bit of the <A HREF="graphreg.htm#08">Bit Mask</A> field determines
whether the corresponding bits in each plane are the result of the previous
step or are copied directly from the latch register. This allows the host
CPU to modify only a single bit, by first performing a dummy read to fill
the latch register
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The fifth stage allows specification
of what planes, if any a write operation affects, via the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field. The four bits in this field determine whether
or not the write affects the corresponding plane If the a planes bit is
1 then the data from the previous step will be written to display memory,
otherwise the display buffer location in that plane will remain unchanged.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The four write modes, of
which the current one is set by writing to the <A HREF="graphreg.htm#05">Write
Mode</A> field The four write modes, simply called write modes 0-3, based
on the value of the <A HREF="graphreg.htm#05">Write Mode</A> field are:
<UL>
<LI>
<B>Write Mode 0:</B></LI>

<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 0 is the standard
and most general write mode. While the other write modes are designed to
perform a specific task, this mode can be used to perform most tasks as
all five operations are performed on the data. The data byte from the host
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
field, then is replicated across all four planes. Then the <A HREF="graphreg.htm#01">Enable
Set/Reset</A> field selects which planes will receive their values from
the host data and which will receive their data from that plane's <A HREF="graphreg.htm#00">Set/Reset</A>
field location. Then the operation specified by the <A HREF="graphreg.htm#03">Logical
Operation</A> field is performed on the resulting data and the data in
the read latches. The <A HREF="graphreg.htm#08">Bit Mask</A> field is then
used to select between the resulting data and data from the latch register.
Finally, the resulting data is written to the display memory planes enabled
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
<LI>
<B>Write Mode 1:</B></LI>

<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 1 is used to
transfer the data in the latches register directly to the screen, affected
only by the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
This can facilitate rapid transfer of data on byte boundaries from one
area of video memory to another or filling areas of the display with a
pattern of 8 pixels. When Write Mode 0 is used with the <A HREF="graphreg.htm#08">Bit
Mask</A> field set to 00000000b the operation of the hardware is identical
to this mode, although it is entirely possible that this mode is faster
on some cards.
<LI>
<B>Write Mode 2:</B></LI>

<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 2 is used to
unpack a pixel value packed into the lower 4 bits of the host data byte
into the 4 display planes. In the byte from the host, the bit representing
each plane will be replicated across all 8 bits of the corresponding planes.
Then the operation specified by the <A HREF="graphreg.htm#03">Logical Operation</A>
field is performed on the resulting data and the data in the read latches.
The <A HREF="graphreg.htm#08">Bit Mask</A> field is then used to select
between the resulting data and data from the latch register. Finally, the
resulting data is written to the display memory planes enabled in the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field.
<LI>
<B>Write Mode 3:</B></LI>

<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Write Mode 3 is used
when the color written is fairly constant but the <A HREF="graphreg.htm#08">Bit
Mask</A> field needs to be changed frequently, such as when drawing single
color lines or text. The value of the <A HREF="graphreg.htm#00">Set/Reset</A>
field is expanded as if the <A HREF="graphreg.htm#01">Enable Set/Reset</A>
field were set to 1111b, regardless of its actual value. The host data
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
field, then is ANDed with the <A HREF="graphreg.htm#08">Bit Mask</A> field.
The resulting value is used where the <A HREF="graphreg.htm#08">Bit Mask</A>
field normally would be used, selecting data from either the expansion
of the <A HREF="graphreg.htm#00">Set/Reset</A> field or the latch register.
Finally, the resulting data is written to the display memory planes enabled
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>
